package com.coldworks.coldjoke.task;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.app.AlertDialog.Builder;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.net.Uri;
import android.os.AsyncTask;
import android.widget.Toast;

import org.apache.http.HttpEntity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.coldworks.base.manager.BaseNetworkManager;
import com.coldworks.base.manager.BaseStorageManager;
import com.coldworks.base.util.BaseCONST;
import com.coldworks.coldjoke.R;
import com.coldworks.coldjoke.util.CONST;

public class DownloadApkTask extends AsyncTask<Void, Integer, Integer> {
	protected final Logger log = LoggerFactory.getLogger(this.getClass());
	private Context context; // 主UI线程上下文
	private String downloadURL; // 下载地址
	private String localFileStr; // 本地保存地址
	private boolean installAfterDownload; // 是否下载完后直接进行安装
	private boolean askForInstall; // 是否询问用户安装还是下载完后直接安装
	private boolean existBeforeInstall; // 安装前是否先退出应用程序

	private ProgressDialog downPrg;
	private int count; // 版本更新下载进度 - 当前值
	private int total; // 版本更新下载进度 - 总值

	public DownloadApkTask(Context context, String downloadURL,
			String localFileStr, boolean installAfterDownload,
			boolean askForInstall, boolean existBeforeInstall) {
		this.context = context;
		this.downloadURL = downloadURL;
		this.localFileStr = localFileStr;
		this.installAfterDownload = installAfterDownload;
		this.askForInstall = askForInstall;
		this.existBeforeInstall = existBeforeInstall;
		this.count = 0;
		this.total = -1;
		log.info("" + downloadURL + " " + localFileStr + " "
				+ installAfterDownload + " " + askForInstall + " "
				+ existBeforeInstall);
	}

	@SuppressWarnings("deprecation")
	@Override
	protected void onPreExecute() {

		downPrg = new ProgressDialog(context);
		downPrg.setIndeterminate(false);
		downPrg.setCancelable(false);
		downPrg.setTitle(context.getString(R.string.download_apk_connecting));
		downPrg.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
		downPrg.setButton(context.getString(R.string.cancel),
				new DialogInterface.OnClickListener() {
					@Override
					public void onClick(DialogInterface dialog, int which) {
						downPrg.dismiss();
						DownloadApkTask.this.cancel(true);
					}
				});
		downPrg.show();

	}

	@Override
	protected Integer doInBackground(Void... params) {
		log.info("downloading");
		File file = new File(this.localFileStr);
		if (file.exists()) {
			file.delete();
		}
		try {
			file.createNewFile();
		} catch (IOException e) {
			log.error("", e);
			return BaseCONST.OP.ERR_IO;
		}
		InputStream is = null;
		FileOutputStream fos = null;
		try {
			HttpEntity entity = BaseNetworkManager.getInstance().httpGETEntity(
					context, this.downloadURL);
			int size = (int) entity.getContentLength();

			if (BaseStorageManager.getInstance().getAvailableStore(
					BaseStorageManager.getInstance().getSdRoot()) < size) {
				return BaseCONST.OP.ERR_OUT_OF_STORE;
			}
			this.publishProgress(size);
			is = entity.getContent();
			if (is == null) {
				return BaseCONST.OP.ERR_NET;
			}
			fos = new FileOutputStream(file);
			byte[] buf = new byte[BaseCONST.HTTP.BUFFER_SIZE];
			int ch = -1;
			while ((ch = is.read(buf)) != -1) {
				if (isCancelled()) {
					throw new InterruptedException();
				}
				this.count += ch;
				fos.write(buf, 0, ch);
				this.publishProgress(this.count);
			}
			fos.flush();
			if (fos != null)
				fos.close();
			if (this.count == size) {
				return BaseCONST.OP.SUCC;
			} else {
				return BaseCONST.OP.ERR_IO;
			}
		} catch (IOException e) {
			log.error("", e);
			return BaseCONST.OP.ERR_IO;
		} catch (InterruptedException e) {
			log.error("", e);
			return BaseCONST.OP.CANCEL;
		} catch (Exception e) {
			log.error("", e);
			return BaseCONST.OP.ERR_NET;
		} finally {
			try {
				if (is != null) {
					is.close();
				}
			} catch (IOException e) {
				log.error("", e);
			}
			try {
				if (fos != null) {
					fos.close();
				}
			} catch (IOException e) {
				log.error("", e);
			}
		}
	}

	@SuppressWarnings("deprecation")
	@Override
	protected void onProgressUpdate(Integer... progress) {
		if (this.total == -1) {
			this.total = progress[0];
			downPrg.setTitle(context.getString(R.string.downloading_apk));
			downPrg.setButton(context.getString(R.string.cancel),
					new DialogInterface.OnClickListener() {

						@Override
						public void onClick(DialogInterface dialog, int which) {
							downPrg.dismiss();
							DownloadApkTask.this.cancel(true);
						}
					});
			downPrg.setMax(this.total);
			downPrg.setProgress(0);
			log.info("progress bar begin");
		} else if (this.downPrg != null) {
			downPrg.setProgress(progress[0]);
		}
	}

	@Override
	protected void onPostExecute(Integer result) {
		if (this.downPrg != null) {
			this.downPrg.dismiss();
		}
		switch (result) {
		case BaseCONST.OP.SUCC:
			log.info("progress bar finish");
			if (this.installAfterDownload) {
				if (this.askForInstall) {

					Builder builder = new AlertDialog.Builder(context);
					builder.setTitle(context.getResources().getString(
							R.string.tip));
					builder.setMessage(context.getResources().getString(
							R.string.install_apk_text));
					builder.setCancelable(true);
					builder.setPositiveButton(
							context.getResources().getString(
									R.string.install_apk_ok),
							new OnClickListener() {

								@Override
								public void onClick(DialogInterface dialog,
										int which) {

									DownloadApkTask.this.install();
								}
							});

					builder.setNegativeButton(
							context.getResources().getString(
									R.string.install_apk_no),
							new OnClickListener() {

								@Override
								public void onClick(DialogInterface dialog,
										int which) {

								}
							});

				} else {
					DownloadApkTask.this.install();
				}
			}
			break;
		// 下载遇到IO异常
		case BaseCONST.OP.ERR_IO:
			log.info("stop by io err");
			new AlertDialog.Builder(context)
					.setTitle(R.string.tip)
					.setCancelable(false)
					.setMessage(context.getString(R.string.install_apk_badfile))
					.setPositiveButton(context.getString(R.string.back),
							new DialogInterface.OnClickListener() {
								public void onClick(DialogInterface dialog,
										int which) {
									dialog.dismiss();
								}
							}).show();
			// 下载遇到网络异常
			break;
		case BaseCONST.OP.ERR_NET:
			log.info("stop by network err");
			new AlertDialog.Builder(context)
					.setTitle(R.string.tip)
					.setCancelable(false)
					.setMessage(context.getString(R.string.err_connecting))
					.setPositiveButton(context.getString(R.string.back),
							new DialogInterface.OnClickListener() {
								public void onClick(DialogInterface dialog,
										int which) {
									dialog.dismiss();
								}
							}).show();
			break;
		// 下载被用户中断
		case BaseCONST.OP.CANCEL:
			log.info("stop by cancel");
			break;
		case BaseCONST.OP.ERR_OUT_OF_STORE:
			Toast.makeText(context, R.string.err_out_of_store,
					Toast.LENGTH_LONG).show();
			break;
		}
	}

	/*
	 * 如果已经下载新版文件则调用此方法进行安裝
	 */
	private void install() {
		Intent i = new Intent();
		i.setAction(Intent.ACTION_VIEW);
		i.setDataAndType(Uri.fromFile(new File(this.localFileStr)),
				CONST.LOCAL.INSTALL_CMD);
		this.context.startActivity(i);
		if (this.existBeforeInstall) {
			this.downPrg.cancel();
			((Activity) this.context).finish();
		}
		log.info("start installing");
	}

}